using System;

using FineCollection.Intf;
using NUnit.Framework;

using FineCollection.Test;



namespace FineCollection.Cont
{
    [TestFixture]
    public class LinkList_test
    {
        // ReSharper disable UseObjectOrCollectionInitializer
        // ReSharper disable ConvertToConstant.Local


        [Test]
        public void Test_Add1()
        {
            object x = "He-he";

            var list = new LinkList<object>();

            list.Add(x);

            list.First  ._same_(x);
            list.Last   ._same_(x);
        }


        [Test]
        public void Test_Add3()
        {
            object a = "aaa",
                   b = "bbb",
                   c = "ccc";

            var list = new LinkList<object>();

            list.Add(a);
            list.Add(b);
            list.Add(c);

            list.First      ._same_(a);
            list.Last       ._same_(c);

            list.ToArray()  ._array_(a,b,c);
        }


        [Test]
        public void Test_InsertAtBegin_IntoEmptyList()
        {
            object x = "Ha-ha";

            var list = new LinkList<object>();

            list.InsertAtBegin(x);

            list.First._same_(x);
            list.Last._same_(x);
        }


        [Test]
        public void Test_InsertAtBegin_Basic()
        {
            object a = "aaaaa";
            object b = "bbbbb";
            object x = "Ha-ha";

            var list = new LinkList<object>();
            list.Add(a);
            list.Add(b);

            list.InsertAtBegin(x);

            list.First._same_(x);

            list.ToArray() ._array_(x, a, b);
        }


        [Test]
        public void Test_Basic1()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            list.Count  ._equals_(3);
            list.First  ._equals_(111L);
            list.Last   ._equals_(333L);
        }


        [Test]
        public void Test_Basic_ToArray()
        {
            var list = new LinkList<long> { 111L, 222L, 333L, 444L, 555L };
            var array = list.ToArray();
            array._array_(111L, 222L, 333L, 444L, 555L);
        }


        [Test]
        public void Test_Iterator()
        {
            var list = new LinkList<long> { 111L, 222L, 333L, 444L, 555L };
            var it = list.TakeIterator();

            it.Next();
            it.Current ._equals_(111L); 
            it.Next();
            it.Current ._equals_(222L); 
            it.Next();
            it.Current ._equals_(333L); 
            it.Next();
            it.Current ._equals_(444L); 
            it.Next();
            it.Current ._equals_(555L); 
            it.Next();
        }


        [Test]
        public void Test_IteratorWhere()
        {
            var list = new LinkList<long> { 111L, 222L };
            var it = list.TakeIterator();

            it.Where  ._equals_((sbyte)-1);
            it.Next();
            it.Where  ._equals_((sbyte)0);
            it.Next();
            it.Where  ._equals_((sbyte)0);
            it.Next();
            it.Where  ._equals_((sbyte)+1);
        }


        [Test]
        public void Test_Iterator_ReplaceCurrent()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();
            it.Next();
            it.Next(); // 222

            long oldOne = 
                it.ReplaceCurrent(777L);

            oldOne ._equals_(222L);

            list.ToArray() ._array_(111L, 777L, 333L);
        }


        [Test]
        [ExpectedException(typeof(OutOfCollectionException))]
        public void Test_Iterator_ReplaceCurrent_BeforeBegin()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();

            it.ReplaceCurrent(777L);
        }


        [Test]
        [ExpectedException(typeof(OutOfCollectionException))]
        public void Test_Iterator_InsertBefore_BeforeBegin()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();

            it.InsertBefore(777L);
        }


        [Test]
        public void Test_Iterator_InsertBefore_Inside()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();
            it.Next();
            it.Next(); // 222

            it.InsertBefore(777L);

            list.ToArray() ._array_(111L, 777L, 222L, 333L);
        }


        [Test]
        public void Test_Iterator_InsertBefore_BehindEnd()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();
            it.Next();
            it.Next(); 
            it.Next(); 
            it.Next(); // behind th end

            it.InsertBefore(777L);

            list.ToArray() ._array_(111L, 222L, 333L, 777L);
        }


        [Test]
        public void Test_Iterator_InsertAfter_BeforeBegin()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();

            it.InsertAfter(777L);

            list.ToArray() ._array_(777L, 111L, 222L, 333L);
        }


        [Test]
        public void Test_Iterator_InsertAfter_Inside()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();
            it.Next();
            it.Next(); // 222

            it.InsertAfter(777L);

            list.ToArray() ._array_(111L, 222L, 777L, 333L);
        }


        [Test]
        [ExpectedException(typeof(OutOfCollectionException))]
        public void Test_Iterator_InserAfter_BehindEnd()
        {
            var list = new LinkList<long> { 111L, 222L, 333L };
            var it = list.TakeIterator();
            it.Next();
            it.Next(); 
            it.Next(); 
            it.Next(); // behind th end

            it.InsertAfter(777L);
        }


        [Test]
        public void Test_ExcludeFirst()
        {
            var list = new LinkList<long> {111L, 222L, 333L};
            list.ExcludeFirst();

            list.ToArray()  ._array_(222L, 333L);
        }


        [Test]
        public void Test_ExcludeLast()
        {
            var list = new LinkList<long> {111L, 222L, 333L};
            list.ExcludeLast();

            list.ToArray()  ._array_(111L, 222L);
        }


        [Test]
        public void Test_ExcludeFirstUsingIterator()
        {
            var list = new LinkList<long> {111L, 222L, 333L};
            var it = list.TakeIterator();

            it.Next();
            it.Exclude() ._equals_(111L);

            list.ToArray()  ._array_(222L, 333L);
        }


        [Test]
        public void Test_ExcludeMiddleUsingIterator()
        {
            var list = new LinkList<long> {111L, 222L, 333L};
            var it = list.TakeIterator();

            it.Next();
            it.Next();
            it.Exclude() ._equals_(222L);

            list.ToArray()  ._array_(111L, 333L);
        }


        [Test]
        public void Test_ExcludeLastUsingIterator()
        {
            var list = new LinkList<long> {111L, 222L, 333L};
            var it = list.TakeIterator();

            it.Next();
            it.Next();
            it.Next();
            it.Exclude() ._equals_(333L);

            list.ToArray()  ._array_(111L, 222L);
        }


        [Test]
        public void Test_ExtractSequence_Basic()
        {
            var list = 
                new LinkList<long> { 11L, 22L, 33L, 44L, 55L, 66L, 77L };
            var it = list.TakeIterator();

            it.Next();
            it.Next();
            it.Next(); it.Current._equals_(33L);

            var extracted = it.ExtractSequence(x => x <= 55L);

            list.ToArray()._array_(11L, 22L, 66L, 77L);
            extracted.ToArray()._array_(33L, 44L, 55L);
        }


        [Test]
        public void Test_ExtractSequence_Count()
        {
            var list =
                new LinkList<long> { 11L, 22L, 33L, 44L, 55L, 66L, 77L };
            var it = list.TakeIterator();

            it.Next();
            it.Next();
            it.Next(); it.Current._equals_(33L);

            var extracted = it.ExtractSequence(x => x <= 55L);

            list.Count._equals_(4);
            extracted.Count._equals_(3);
        }


        [Test]
        public void Test_ExtractSequence_AtBegin()
        {
            var list =
                new LinkList<long> { 11L, 22L, 33L, 44L, 55L, 66L, 77L };
            var it = list.TakeIterator();

            it.Next(); it.Current._equals_(11L);

            var extracted = it.ExtractSequence(x => x <= 33L);

            list.ToArray()._array_(44L, 55L, 66L, 77L);
            extracted.ToArray()._array_(11L, 22L, 33L);
        }


        [Test]
        public void Test_ExtractSequence_AtEnd()
        {
            var list =
                new LinkList<long> { 11L, 22L, 33L, 44L, 55L, 66L, 77L };
            var it = list.TakeIterator();

            it.Next();
            it.Next();
            it.Next();
            it.Next();
            it.Next(); it.Current._equals_(55L);

            var extracted = it.ExtractSequence(x => true);

            list.ToArray()._array_(11L, 22L, 33L, 44L);
            extracted.ToArray()._array_(55L, 66L, 77L);
        }


        [Test]
        public void Test_ExtractSequence_FalsePredicate()
        {
            var list =
                new LinkList<long> { 11L, 22L, 33L };
            var it = list.TakeIterator();

            it.Next(); 
            it.Next(); 

            var extracted = it.ExtractSequence(x => false);

            list.ToArray()._array_(11L, 33L);
            extracted.ToArray()._array_(22L);
        }


        [Test]
        public void Test_ExtractSequence_WholeList()
        {
            var list =
                new LinkList<long> { 11L, 22L, 33L };
            var it = list.TakeIterator();

            it.Next();

            var extracted = it.ExtractSequence(x => true);

            list.IsEmpty._true_();
            extracted.ToArray()._array_(11L, 22L, 33L);
        }


        [Test]
        public void Test_CopyTo_OrdinalArray()
        {
            var list = new LinkList<long> { 1111L, 2222L, 3333L };
            long[] array = new long[3];

            list.CopyTo(array, 0);

            array[0]  ._equals_(1111L);
            array[1]  ._equals_(2222L);
            array[2]  ._equals_(3333L);
        }


    }
}